package com.annotation;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @功能：动态创建对象执行方法
 * @版本： V1
 * @版权： 信息技术有限公司（http://www.mychery.com/）
 * @作者： 磐石战队开发组  00355760
 * @日期： 2024/8/10 14:55
 * 方法（Method）、属性（Field）、构造器（Constructor）对象都有setAccessible()方法，其作用是设置安全检查开关，默认为false，
 * 当参数值为true时，有两个好处：①提高访问权限，使得原来无法访问的私有成员也可以访问；②提高反射的效率；
 */
public class demo09 {
    /**
     * 创建类的对象(两种)
     * newInstance()
     * 本质上是调用了无参构造器且构造器访问权限满足
     * <p>
     * 构造器创建对象
     * 通过getDeclaredConstructor(参数.class)获取本类指定类型构造器
     * 用构造器.newInstance(“Xxx”)传入构造参数
     * <p>
     * 调用类的方法并获取返回值
     * 通过类得到方法对象，对象中invoke方法 (invoke返回方法返回值)
     * class —> method —> invoke(对象，方法参数的值且可以为null)
     * <p>
     * 获取类方法的返回值类型
     * 通过类得到方法对象，对象中getReturnType方法
     * class —> field —> getReturnType()
     * <p>
     * 获取类方法的参数类型
     * 通过类得到方法对象，对象中getParameterTypes方法
     * class —> field —> getParameterTypes()
     * <p>
     * 调用类的属性
     * 通过类得到方法对象，对象中set方法
     * class —> field —> set(对象，方法参数的值)
     * <p>
     * 获取调用类的属性
     * 通过类得到方法对象，对象中get方法
     * class —> field —> get(对象)
     * <p>
     * setAccessible(boolean x)
     * 启动和禁用访问安全检查的开关
     * 作用：
     * 1.提高反射效率
     * 2.访问私有
     */
    // 动态的创建对象
    public static void main(String[] args) throws Exception {
        // 获得Class对象
        Class c1 = Class.forName("cn.com.annotation.User");
        // 通过newInstance()构造一个对象
        // 本质上调用了无参构造器
        User user = (User) c1.newInstance();
        System.out.println(user);
        // 通过构造器创建对象
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        User user1 = (User) constructor.newInstance("jacky", 1, 1);
        System.out.println(user1);
        // 通过反射调用普通方法
        User user3 = (User) c1.newInstance();
        // 通过反射获取一个方法
        Method setName = c1.getDeclaredMethod("setName", String.class);
        // invoke : 激活的意思，传入User对象和方法对应的参数(对象, "方法的值")
        setName.invoke(user3, "jacky");
        System.out.println(user3.getName());
        // 通过反射操作属性
        User user4 = (User) c1.newInstance();
        Field name = c1.getDeclaredField("name");
        // 不能直接操作私有属性，需要关闭程序的安全检测，属性或方法的setAccessible(true)
        name.setAccessible(true);
        name.set(user4, "jakcy1");
        System.out.println(user4.getName());
    }

}

